package com.leyou.item.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fasterxml.jackson.core.type.TypeReference;
import com.leyou.common.dto.PageDTO;
import com.leyou.common.exception.LyException;
import com.leyou.common.utils.JsonUtils;
import com.leyou.item.dto.*;
import com.leyou.item.entity.Sku;
import com.leyou.item.entity.Spu;
import com.leyou.item.entity.SpuDetail;
import com.leyou.item.mapper.SpuMapper;
import com.leyou.item.service.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;


@Service
public class SpuServiceImpl extends ServiceImpl<SpuMapper, Spu> implements SpuService {
    @Autowired
    SpecGroupService specGroupService;
    @Autowired
    SpuDetailServiceImpl spuDetailService;
    @Autowired
    SkuService skuService;
    @Autowired
    private BrandService brandService;
    @Autowired
    private CategoryService categoryService;

    @Override
    public PageDTO<SpuDTO> pageDTOResponseEntity(Long page, Long rows, Long brandId, Long id, Boolean saleable, Long categoryId) {
        if (page == null || rows == null) {
            page = 1L;
            rows = 5L;
        }
        IPage<Spu> iPage = new Page<>(page, rows);
        IPage<Spu> spuIPage = this.page(iPage, new QueryWrapper<Spu>()
                .eq(brandId != null, "brand_id", brandId)
                .eq(id != null, "id", id)
                .eq(saleable != null, "saleable", saleable)
                .eq(categoryId != null, "cid3", categoryId));

        List<SpuDTO> spuDTOS = SpuDTO.convertEntityList(spuIPage.getRecords());
        spuDTOS.forEach(spuDTO -> {

            //根据分类id的集合查询对应的分类集合，并取出分类名称并拼接为字符串
            String names = this.categoryService
                    .getCategoryPyIds(spuDTO.getCategoryIds())
                    .stream()
                    .map(CategoryDTO::getName)
                    .collect(Collectors.joining("/"));

            //TODO 查询要考虑缓存，缓存击穿

            spuDTO.setCategoryName(names);
            //根据brandId查询对应的品牌
            spuDTO.setBrandName(this.brandService.getById(spuDTO.getBrandId()).getName());
        });


        return new PageDTO<SpuDTO>(spuIPage.getTotal(), spuIPage.getPages(), spuDTOS);
    }

    @Override
    public List<SpecGroupDTO> getDTOResponseEntity(Long id, Boolean searching) {
        Long cid3 = this.getById(id).getCid3();
        List<SpecGroupDTO> specGroupDTOS = specGroupService.queryGroupAndDetailByCategories(cid3);

        String description = spuDetailService.getById(id).getSpecification();

        Map map = JsonUtils.nativeRead(description, new TypeReference<HashMap>() {
        });

        specGroupDTOS.forEach(specGroupDTO -> {
            ArrayList<SpecParamDTO> cope = new ArrayList<>();
            specGroupDTO.getParams().forEach(specParamDTO -> {

                specParamDTO.setValue(map.get(specParamDTO.getId() + ""));
                System.out.println(specGroupDTO.toString());

                if (specParamDTO.getSearching() != searching && searching != null) {
                    cope.add(specParamDTO);
                }
            });
            specGroupDTO.getParams().removeAll(cope);
        });

        return specGroupDTOS;
    }

    @Override
    public void saveGoods(SpuDTO spuDTO) {
        // 1.新增Spu
        Spu spu = spuDTO.toEntity(Spu.class);
        spu.setSaleable(false);
        boolean success = saveOrUpdate(spu);
        if (!success) {
            throw new LyException(500, "新增商品失败");
        }

        // 2.新增SpuDetail
        if (spuDTO.getSpuDetail() != null) {
            SpuDetail spuDetail = spuDTO.getSpuDetail().toEntity(SpuDetail.class);
            spuDetail.setSpuId(spu.getId());
            success = spuDetailService.saveOrUpdate(spuDetail);
            if (!success) {
                throw new LyException(500, "新增商品详情失败");
            }
        }
        // 3.新增Sku
        if (spuDTO.getSkus().size() != 0 ) {
            List<Sku> list = spuDTO.getSkus().stream().map(skuDTO -> {
                Sku sku = skuDTO.toEntity(Sku.class);
                sku.setSaleable(false);
                sku.setSpuId(spu.getId());
                return sku;
            }).collect(Collectors.toList());
            // 批量新增
            skuService.saveOrUpdateBatch(list);
        }
    }



    @Override
    @Transactional
    public void updateSaleable(Long id, Boolean saleable) {
        // 1.更新SPU
        Spu spu = new Spu();
        spu.setId(id);
        spu.setSaleable(saleable);
        boolean success = updateById(spu);
        if (!success) {
            throw new LyException(500, "更新失败");
        }
        // 2.更新sku
        success = skuService.update().eq("spu_id", id).set("saleable", saleable).update();
        if (!success) {
            throw new LyException(500, "更新失败");
        }
    }

    @Override
    public SpuDTO queryGoodsById(Long id) {
        // 1.查询spu
        // 1.1.查询
        Spu spu = getById(id);
        if (spu == null) {
            throw new LyException(400, "商品id不存在！");
        }
        // 1.2.转换DTO
        SpuDTO spuDTO = new SpuDTO(spu);

        // 2.查询spuDetail
        SpuDetail detail = spuDetailService.getById(id);
        if (detail == null) {
            throw new LyException(400, "商品id不存在！");
        }
        spuDTO.setSpuDetail(new SpuDetailDTO(detail));

        // 3.查询sku
        List<Sku> list = skuService.query().eq("spu_id", id).list();
//        if(CollectionUtils.isEmpty(list)){
//            throw new LyException(400, "商品id不存在！");
//        }
        spuDTO.setSkus(SkuDTO.convertEntityList(list));

        // 4.准备商品分类和品牌名称
//        handleCategoryAndBrandName(spuDTO);

        return spuDTO;
    }

    @Override
    @Transactional
    public void updateGoods(SpuDTO spuDTO) {

        if(spuDTO.getSpuDetail()!=null){
            spuDTO.setId(spuDTO.getSpuDetail().getSpuId());
        }

        if(spuDTO.getSkus()!=null){
            spuDTO.setId(spuDTO.getSkus().get(0).getSpuId());
            //得到要删除的skus的ids
            List<Long> delSkuIds = spuDTO
                    .getSkus()
                    .stream()
                    .filter(skuDTO -> skuDTO.getSaleable() != null)
                    .map(SkuDTO::getId)
                    .collect(Collectors.toList());
            //删除skus
            this.skuService.removeByIds(delSkuIds);

            //得到去除了要删除的skus的skus
            List<SkuDTO> skuDTOS = spuDTO
                    .getSkus()
                    .stream()
                    .filter(skuDTO -> skuDTO.getSaleable() == null)
                    .collect(Collectors.toList());
            //从新把新skus分装回去
            spuDTO.setSkus(skuDTOS);

        }
        //执行修改
        saveGoods(spuDTO);
    }
}